<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>animation</title>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <style>
        #demo, .demo, .content .demo {
            border: 1px solid #eee;
            border-radius: 2px;
            padding: 25px 35px;
            margin-top: 1em;
            margin-bottom: 40px;
            font-size: 1.2em;
            line-height: 1.5em;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            overflow-x: auto;
        }
        .fade-enter-active, .fade-leave-active {
            transition: opacity .5s;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
            opacity: 0;
        }

        /* 可以设置不同的进入和离开动画 */
        /* 设置持续时间和动画函数 */
        .slide-fade-enter-active {
            transition: all .3s ease;
        }
        .slide-fade-leave-active {
            transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
        }
        .slide-fade-enter, .slide-fade-leave-to /* .slide-fade-leave-active for below version 2.1.8 */ {
            transform: translateX(10px);
            opacity: 0;
        }

        .bounce-enter-active {
            animation: bounce-in .5s;
        }
        .bounce-leave-active {
            animation: bounce-in .5s reverse;
        }
        @keyframes bounce-in {
            0% {
                transform: scale(0);
            }
            50% {
                transform: scale(1.5);
            }
            100% {
                transform: scale(1);
            }
        }

        .component-fade-enter-active, .component-fade-leave-active {
            transition: opacity .3s ease;
        }
        .component-fade-enter, .component-fade-leave-to
            /* .component-fade-leave-active for below version 2.1.8 */ {
            opacity: 0;
        }

        .list-item {
            display: inline-block;
            margin-right: 10px;
        }
        .list-enter-active, .list-leave-active {
            transition: all 1s;
        }
        .list-enter, .list-leave-to
            /* .list-leave-active for below version 2.1.8 */ {
            opacity: 0;
            transform: translateY(30px);
        }
        .flip-list-move {
           transition: transform 1s;
        }
        .list-complete-item {
            transition: all 1s;
            display: inline-block;
            margin-right: 10px;
        }
        .list-complete-enter, .list-complete-leave-to
            /* .list-complete-leave-active for below version 2.1.8 */ {
            opacity: 0;
            transform: translateY(30px);
        }
        .list-complete-leave-active {
            position: absolute;
        }
        .sudoku-container {
            display: flex;
            flex-wrap: wrap;
            width: 238px;
            margin-top: 10px;
        }
        .cell {
            display: flex;
            justify-content: space-around;
            align-items: center;
            width: 25px;
            height: 25px;
            border: 1px solid #aaa;
            margin-right: -1px;
            margin-bottom: -1px;
        }
        .cell:nth-child(3n) {
            margin-right: 0;
        }
        .cell:nth-child(27n) {
            margin-bottom: 0;
        }
        .cell-move {
            transition: transform 1s;
        }
        .example-7-color-preview {
            display: inline-block;
            width: 50px;
            height: 50px;
        }
        svg { display: block; }
        polygon { fill: #41B883; }
        circle {
            fill: transparent;
            stroke: #35495E;
        }
        input[type="range"] {
            display: block;
            width: 100%;
            margin-bottom: 15px;
        }
    </style>
</head>
<body>
    <div id="demo">
        <button v-on:click="show = !show">
            Toggle
        </button>
        <transition name="fade">
            <p v-if="show">hello</p>
        </transition>
    </div>

    <div id="example-1">
        <button @click="show = !show">
            Toggle render
        </button>
        <transition name="slide-fade">
            <p v-if="show">hello</p>
        </transition>
    </div>

    <div id="example-2">
        <button @click="show = !show">
            Toggle show
        </button>
        <transition name="bounce" >
            <p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p>
        </transition>
    </div>

    <div id="example-3">
        <button @click="show = !show">
            Toggle render
        </button>
        <transition
            :duration="{ enter: 500, leave: 800 }"
            name="custom-classes-transition"
            enter-active-class="animated tada"
            leave-active-class="animated bounceOutRight"
        >
            <p v-if="show">hello</p>
        </transition>
    </div>

    <div id="example-4">
        <button @click="show = !show">
            Toggle
        </button>
        <transition
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:leave="leave"
            v-bind:css="false"
        >
            <p v-if="show">Demo</p>
        </transition>
    </div>
    <div id="transition-components-demo" class="demo">
        <input type="radio" value="v-a" id="a" v-model="view"><label for="a">A</label>
        <input type="radio" value="v-b" id="b" v-model="view"><label for="b">B</label>
        <transition name="component-fade" mode="out-in">
            <component v-bind:is="view"></component>
        </transition>
    </div>

    <div id="list-demo" class="demo">
        <button v-on:click="add">Add</button>
        <button v-on:click="remove">Remove</button>
        <transition-group name="list" tag="p">
            <span v-for="item in items" v-bind:key="item" class="list-item">
                {{item}}
            </span>
        </transition-group>
    </div>

    <div id="flip-list-demo" class="demo">
        <button v-on:click="shuffle">Shuffle</button>
        <transition-group name="flip-list" tag="ul">
            <li v-for="item in items" v-bind:key="item">
                {{item}}
            </li>
        </transition-group>
    </div>

    <div id="list-complete-demo" class="demo">
        <button v-on:click="shuffle">Shuffle</button>
        <button v-on:click="add">Add</button>
        <button v-on:click="remove">Remove</button>
        <transition-group name="list-complete" tag="p">
            <span
                v-for="item in items"
                v-bind:key="item"
                class="list-complete-item"
            >{{item}}
            </span>
        </transition-group>
    </div>

    <div id="sudoku-demo" class="demo"><strong>Lazy Sudoku</strong>
        <p>Keep hitting the shuffle button until you win.</p> 
        <button v-on:click="shuffle">
            Shuffle
        </button>
        
        <transition-group name="cell" class="sudoku-container" tag="div">
            <div
                v-for="item in items"
                v-bind:key="item.id"
                class="cell"
            >
                {{item.number}}
            </div>
        </transition-group>
    </div>

    <div id="staggered-list-demo">
        <input v-model="query">
        <transition-group
            name="staggered-fade"
            tag="ul"
            v-bind:css="false"
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:leave="leave"
        >
            <li
                v-for="(item,index) in computedList"
                v-bind:key="item.msg"
                v-bind:data-index="index"
            >{{ item.msg }}</li>
        </transition-group>
    </div>

    <div id="dynamic-fade-demo" class="demo">
        Fade In: <input type="range" v-model="fadeInDuration" min="0" v-bind:max="maxFadeDuration">
        Fade Out: <input type="range" v-model="fadeOutDuration" min="0" v-bind:max="maxFadeDuration">
        <transition
            v-bind:css="false"
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:leave="leave"
        >
            <p v-if="show">hello</p>
        </transition>
        <button
            v-if="stop"
            v-on:click="stop = false; show = false"
        >Start animating</button>
        <button
            v-else
            v-on:click="stop = true"
        >Stop it!</button>
    </div>

    <div id="animated-number-demo">
      <input v-model.number="number" type="number" step="20">
      <p>{{ animatedNumber }}</p>
    </div>
    

    <div id="example-7">
        <input
            v-model="colorQuery"
            v-on:keyup.enter="updateColor"
            placeholder="Enter a color"
        >
        <button v-on:click="updateColor">Update</button>
        <p>Preview:</p>
        <span
            v-bind:style="{ backgroundColor: tweenedCSSColor }"
            class="example-7-color-preview"
        ></span>
        <p>{{ tweenedCSSColor }}</p>
    </div>

    <div id="app">
        <svg width="200" height="200">
            <polygon :points="points"></polygon>
            <circle cx="100" cy="100" r="90"></circle>
        </svg>
        <label>Sides: {{ sides }}</label>
        <input 
            type="range" 
            min="3" 
            max="500" 
            v-model.number="sides"
        >
        <label>Minimum Radius: {{ minRadius }}%</label>
        <input 
            type="range" 
            min="0" 
            max="90" 
            v-model.number="minRadius"
        >
        <label>Update Interval: {{ updateInterval }} milliseconds</label>
        <input 
            type="range" 
            min="10" 
            max="2000"
            v-model.number="updateInterval"
        >
    </div>
    <div id="example-8">
        <input v-model.number="firstNumber" type="number" step="20"> +
        <input v-model.number="secondNumber" type="number" step="20"> =
        {{ result }}
        <p>
            <animated-integer v-bind:value="firstNumber"></animated-integer> +
            <animated-integer v-bind:value="secondNumber"></animated-integer> =
            <animated-integer v-bind:value="result"></animated-integer>
        </p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/tween.js@16.3.4"></script>
    <script src="js/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js" ></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/color-js@1.0.3"></script>
    <!--
    Velocity 和 jQuery.animate 的工作方式类似，也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>


    <script>
        window.onload = function() {
            new Vue({
                el: "#demo",
                data:{
                    show: true
                }
            })

            new Vue({
                el:"#example-1",
                data:{
                    show:true
                }
            })

            new Vue({
                el:"#example-2",
                data:{
                    show:true
                }
            })

            new Vue({
                el:"#example-3",
                data:{
                    show:true
                }
            })

            new Vue({
                el:"#example-4",
                data:{
                    show:false
                },
                methods:{
                    beforeEnter:function(el) {
                        el.style.opacity = 0
                        el.style.transformOrigin = 'left'
                    },
                    enter:function(el,done) {
                        Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
                        Velocity(el, { fontSize: '1em' }, { complete: done })
                    },
                    leave:function(el,done) {
                        Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
                        Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
                        Velocity(el, {
                            rotateZ: '45deg',
                            translateY: '30px',
                            translateX: '30px',
                            opacity: 0
                        }, { complete: done })
                    }
                }
            })

            new Vue({
                el:"#transition-components-demo",
                data:{
                    view:'v-b'
                },
                components:{
                    'v-a':{
                        template:'<div>Component A</div>'
                    },
                    'v-b':{
                        template:'<div>Component B</div>'
                    }
                }
            })
            
            new Vue({
                el:"#list-demo",
                data:{
                    items:[1,2,3,4,5,6,7,8,9],
                    nextNum:10
                },
                methods:{
                    randomIndex:function() {
                        return Math.floor(Math.random() * this.items.length);
                    },  
                    add:function() {
                        this.items.splice(this.randomIndex(),0,this.nextNum++);
                    },
                    remove:function() {
                        this.items.splice(this.randomIndex(),1);
                    }
                }
            })

            new Vue({
                el:"#flip-list-demo",
                data:{
                    items:[1,2,3,4,5,6,7,8,9]
                },
                methods:{
                    shuffle:function(){
                        this.items = _.shuffle(this.items);
                    }
                }
            })

            new Vue({
                el:"#list-complete-demo",
                data:{
                    items:[1,2,3,4,5,6,7,8,9],
                    nextNum:10
                },
                methods:{
                    randomIndex:function() {
                        return Math.floor(Math.random() * this.items.length)
                    },
                    add:function() {
                        this.items.splice(this.randomIndex(),0,this.nextNum++);
                    },
                    remove:function() {
                        this.items.splice(this.randomIndex(),1);
                    },
                    shuffle:function() {
                        this.items = _.shuffle(this.items);
                    }

                }
            })

            new Vue({
                el:"#sudoku-demo",
                data:{
                    items:Array.apply(null,{length:81})
                        .map(function(_,index){
                            return {
                                id:index,
                                number:index % 9 + 1
                            };
                        })
                },
                methods:{
                    shuffle:function() {
                        this.items = _.shuffle(this.items);
                    }
                }
            })

            new Vue({
                el:"#staggered-list-demo",
                data:{
                    query:'',
                    list:[
                        {msg:'Taylor Swift'},
                        {msg:'Gardenzio Stallone'},
                        {msg:'Arnold Schwarzenegger'},
                        {msg:'Jackie Chan'},
                        {msg:'Jay Chou'}
                    ]
                },
                computed:{
                    computedList: function() {
                        var vm = this;
                        return this.list.filter(function(item) {
                            return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1;
                        })
                    }
                },
                methods:{
                    beforeEnter: function(el) {
                        el.style.opacity = 0;
                        el.style.height = 0;
                    },
                    enter: function(el,done){
                        var delay = el.dataset.index * 150;
                        setTimeout(function() {
                            Velocity(
                                el,
                                {opacity:1,height:'1.6em'},
                                {complete:done}
                            )
                        },delay)
                    },
                    leave:function(el,done) {
                        var delay = el.dataset.index * 150;
                        setTimeout(function() {
                            Velocity(
                                el,
                                {opacity:0,height:0},
                                {complete:done}
                            )
                        },delay)
                    }
                }
            })

            new Vue({
                el: '#dynamic-fade-demo',
                data: {
                    show: true,
                    fadeInDuration: 1000,
                    fadeOutDuration: 1000,
                    maxFadeDuration: 1500,
                    stop: true
                },
                mounted: function () {
                    this.show = false
                },
                methods: {
                    beforeEnter: function (el) {
                    el.style.opacity = 0
                    },
                    enter: function (el, done) {
                    var vm = this
                    Velocity(el,
                        { opacity: 1 },
                        {
                        duration: this.fadeInDuration,
                        complete: function () {
                            done()
                            if (!vm.stop) vm.show = false
                        }
                        }
                    )
                    },
                    leave: function (el, done) {
                    var vm = this
                    Velocity(el,
                        { opacity: 0 },
                        {
                        duration: this.fadeOutDuration,
                        complete: function () {
                            done()
                            vm.show = true
                        }
                        }
                    )
                    }
                }
            })
            new Vue({
                el: '#animated-number-demo',
                data: {
                    number: 0,
                    tweenedNumber: 0
                },
                computed: {
                    animatedNumber: function() {
                    return this.tweenedNumber.toFixed(0);
                    }
                },
                watch: {
                    number: function(newValue) {
                    TweenLite.to(this.$data, 0.5, { tweenedNumber: newValue });
                    }
                }
            })


            var Color = net.brehaut.Color

            new Vue({
                el: '#example-7',
                data: {
                    colorQuery: '',
                    color: {
                    red: 0,
                    green: 0,
                    blue: 0,
                    alpha: 1
                    },
                    tweenedColor: {}
                },
                created: function () {
                    this.tweenedColor = Object.assign({}, this.color)
                },
                watch: {
                    color: function () {
                    function animate () {
                        if (TWEEN.update()) {
                        requestAnimationFrame(animate)
                        }
                    }

                    new TWEEN.Tween(this.tweenedColor)
                        .to(this.color, 750)
                        .start()

                    animate()
                    }
                },
                computed: {
                    tweenedCSSColor: function () {
                    return new Color({
                        red: this.tweenedColor.red,
                        green: this.tweenedColor.green,
                        blue: this.tweenedColor.blue,
                        alpha: this.tweenedColor.alpha
                    }).toCSS()
                    }
                },
                methods: {
                    updateColor: function () {
                    this.color = new Color(this.colorQuery).toRGB()
                    this.colorQuery = ''
                    }
                }
            })
            new Vue({
                el: '#app',
                data: function () {
                    var defaultSides = 10
                    var stats = Array.apply(null, { length: defaultSides })
                        .map(function () { return 100 })
                    return {
                        stats: stats,
                        points: generatePoints(stats),
                    sides: defaultSides,
                    minRadius: 50,
                    interval: null,
                    updateInterval: 500
                    }
                },
                watch: {
                    sides: function (newSides, oldSides) {
                        var sidesDifference = newSides - oldSides
                    if (sidesDifference > 0) {
                        for (var i = 1; i <= sidesDifference; i++) {
                            this.stats.push(this.newRandomValue())
                        }
                    } else {
                        var absoluteSidesDifference = Math.abs(sidesDifference)
                        for (var i = 1; i <= absoluteSidesDifference; i++) {
                            this.stats.shift()
                        }
                    }
                    },
                    stats: function (newStats) {
                            TweenLite.to(
                        this.$data, 
                        this.updateInterval / 1000, 
                        { points: generatePoints(newStats) }
                        )
                    },
                    updateInterval: function () {
                        this.resetInterval()
                    }
                },
                mounted: function () {
                    this.resetInterval()
                },
                methods: {
                    randomizeStats: function () {
                        var vm = this
                        this.stats = this.stats.map(function () {
                        return vm.newRandomValue()
                    })
                    },
                    newRandomValue: function () {
                        return Math.ceil(this.minRadius + Math.random() * (100 - this.minRadius))
                    },
                    resetInterval: function () {
                        var vm = this
                        clearInterval(this.interval)
                    this.randomizeStats()
                        this.interval = setInterval(function () { 
                        vm.randomizeStats()
                    }, this.updateInterval)
                    }
                }
            })

            function valueToPoint (value, index, total) {
                var x     = 0
                var y     = -value * 0.9
                var angle = Math.PI * 2 / total * index
                var cos   = Math.cos(angle)
                var sin   = Math.sin(angle)
                var tx    = x * cos - y * sin + 100
                var ty    = x * sin + y * cos + 100
                return { x: tx, y: ty }
            }

            function generatePoints (stats) {
                var total = stats.length
                return stats.map(function (stat, index) {
                    var point = valueToPoint(stat, index, total)
                    return point.x + ',' + point.y
                }).join(' ')
            }

            // 这种复杂的补间动画逻辑可以被复用
            // 任何整数都可以执行动画
            // 组件化使我们的界面十分清晰
            // 可以支持更多更复杂的动态过渡
            // 策略。
            Vue.component('animated-integer', {
            template: '<span>{{ tweeningValue }}</span>',
            props: {
                value: {
                type: Number,
                required: true
                }
            },
            data: function () {
                return {
                tweeningValue: 0
                }
            },
            watch: {
                value: function (newValue, oldValue) {
                this.tween(oldValue, newValue)
                }
            },
            mounted: function () {
                this.tween(0, this.value)
            },
            methods: {
                tween: function (startValue, endValue) {
                var vm = this
                function animate () {
                    if (TWEEN.update()) {
                    requestAnimationFrame(animate)
                    }
                }

                new TWEEN.Tween({ tweeningValue: startValue })
                    .to({ tweeningValue: endValue }, 500)
                    .onUpdate(function (object) {
                    vm.tweeningValue = object.tweeningValue.toFixed(0)
                    })
                    .start()

                animate()
                }
            }
            })

            // 所有的复杂度都已经从 Vue 的主实例中移除！
            new Vue({
            el: '#example-8',
            data: {
                firstNumber: 20,
                secondNumber: 40
            },
            computed: {
                result: function () {
                return this.firstNumber + this.secondNumber
                }
            }
            })
        }
    </script>
</body>
</html>